const dayjs = require("dayjs");
const fs = require("fs");
const path = require("path");
const config = require("config");
const message = require("./dingding");
const directory = config.get("directory");
var readline = require("readline");
const log4js = require("./logger"),
    logger = log4js.getLogger("info")
var beginTime = +new Date();

/**
 * 扩展Date的Format函数
 * 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，
 * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
 * @param {[type]} fmt [description]
 */
Date.prototype.Format = function (fmt) { //author:
    var o = {
        "M+": this.getMonth() + 1, //月份
        "d+": this.getDate(), //日
        "h+": this.getHours(), //小时
        "m+": this.getMinutes(), //分
        "s+": this.getSeconds(), //秒
        "S": this.getMilliseconds() //毫秒
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}
current_time = (new Date()).Format("yyyy-MM-dd hh:mm:ss")
logger.info(`开始分析日志，分析时间为：${current_time}`); // 获取程序运行时间

if (
    !directory ||
    directory.find(item => !fs.existsSync(item)) ||
    directory.find(item => !fs.statSync(item).isDirectory())
) {
    logger.error("error：文件夹路径错误");
    process.exit();
}
logger.info("分析日志目录为：", directory);

const businessFiles = [];
const suan_fa_files = []; // 算法日志文件

function walk(filePath) {
    //根据文件路径读取文件，返回文件列表
    const files = fs.readdirSync(filePath);
    files.forEach(function (filename) {
        //获取当前文件的绝对路径
        var filedir = path.join(filePath, filename);
        //根据文件路径获取文件信息，返回一个fs.Stats对象
        const stats = fs.statSync(filedir);
        var isFile = stats.isFile(); //是文件
        var isDir = stats.isDirectory(); //是文件夹
        if (isFile) {
            if (filename.indexOf('api-console') !== -1) {
                suan_fa_files.push(filedir)
            } else if (filename.indexOf('dingding') !== -1) {
                businessFiles.push(filedir);
                count==businessFiles.length(filedir);
                console.log(count)
            } else {
                logger.error("error：当前目录下没有包含【dingding】或者【api-console】的文件，请确认目录是否正确！！！");
            }
        }
        if (isDir) {
            walk(filedir); //递归，如果是文件夹，就继续遍历该文件夹下面的文件
        }
    });
}

directory.forEach(walk)

async function readFile(start_dt, handler) {
    const regex = /\d+\-\d+\-\d+\s\d+:\d+:\d+/;
    let rl;
    for (let p of businessFiles) {
        await new Promise((resolve) => {
            rl = readline.createInterface({
                input: fs.createReadStream(p),
                separator: regex,
                encoding: "utf8",
                bufferSize: 2048576,
            });
            logger.info('开始读取业务日志文件：' + p.split('/')[p.split('/').length - 1])
            rl.on('line', (line) => {
                function read(line, last) {
                    const dateMatch = line.match(regex)
                    logger.info("当前业务日志文件匹配到的日期格式为：", dateMatch)
                    if (dateMatch) {
                        let date = dateMatch;
                        if (dayjs(date).isAfter(dayjs(start_dt))) {
                            date = dayjs(date).format("YYYY-MM-DD HH:mm");
                            const pMatch = line.match(/(\[|\")P(\d+)/g) || [];
                            pMatch.forEach((item) => {
                                const grade = item.match(/P(\d+)/)[1];
                                handler(grade, date);
                                logger.info("业务日志[" + p.split('/')[p.split('/').length - 1] + "]下告警日期为：" + date, "告警级别为：P" + grade)
                            });
                        }
                    }
                    if (last) {
                        resolve();
                    }
                }

                read(line)
            });
            rl.on("close", function () {
                // 结束程序
                resolve();
            });
        });
        logger.info('结束读取业务日志文件：' + p.split('/')[p.split('/').length - 1])
    }
}

async function readFileForSuanFa(start_dt, handler) {
    const regex = /\d+\-\d+\-\d+\s\d+:\d+:\d+/;
    let rl;
    for (let p of suan_fa_files) {
        logger.info('开始读取算法日志文件：' + p.split('/')[p.split('/').length - 1])
        await new Promise((resolve) => {
            rl = readline.createInterface({
                input: fs.createReadStream(p),
                separator: regex,
                encoding: "utf8",
                bufferSize: 3048576,
            });
            rl.on('line', (line) => {
                function read(line) {
                    const dateMatch = line.match(regex);
                    logger.info("当前算法日志文件匹配到的日期格式为：", dateMatch)
                    if (dateMatch) {
                        let date = dateMatch;
                        if (new Date(date) > new Date(start_dt)) {
                            date = dayjs(date).format("YYYY-MM-DD HH:mm");
                            const pMatch = line.match(/ALGO\-P(\d+)/g) || [];
                            if (pMatch.length > 0) {
                                pMatch.forEach((item) => {
                                    const grade = item.match(/ALGO\-P(\d+)/)[1];
                                    handler(grade, date);
                                    logger.info("算法日志[" + p.split('/')[p.split('/').length - 1] + "]下告警日期为：" + date, "告警级别为：ALGO-P" + grade)
                                });
                            }
                        }

                    }
                }

                read(line)
            });
            // close事件监听
            rl.on("close", function () {
                // 结束程序
                resolve();
            });
        });
        logger.info('结束读取算日志文件：' + p.split('/')[p.split('/').length - 1])
    }
}

const len = (obj = {}) => Object.keys(obj).length;

async function init() {
    let totalMinutes, start_dt;
    if (dayjs().month() >= 10 - 1) {
        // 第四季度
        start_dt = dayjs().month(9).date(1).format("YYYY-MM-DD");
        totalMinutes = dayjs().diff(start_dt, "minutes");
    } else if (dayjs().month() >= 7 - 1) {
        // 第三季度
        start_dt = dayjs().month(6).date(1).format("YYYY-MM-DD");
        totalMinutes = dayjs().diff(start_dt, "minutes");
    } else if (dayjs().month() > 4 - 1) {
        // 第二季度
        start_dt = dayjs().month(3).date(1).format("YYYY-MM-DD");
        totalMinutes = dayjs().diff(start_dt, "minutes");
    } else {
        // 第一季度
        if (dayjs().year() === 2021) {
            start_dt = '2021-02-01'
        } else {
            start_dt = dayjs().month(0).date(1).format("YYYY-MM-DD");
        }
        totalMinutes = dayjs().diff(start_dt, "minutes");
    }
    const result1 = {};
    const result2 = {};
    await readFile(start_dt, function (grade, date) {
        date = dayjs(date).format("YYYY-MM-DD HH:mm");
        if (grade === "1" || grade === "2") {
            result1[date] = true;
        }
        if (!result2[grade]) {
            result2[grade] = {};
        }
        result2[grade][date] = true;
    });

    const result3 = {}
    const result4 = {};
    await readFileForSuanFa(start_dt, function (grade, date) {
        date = dayjs(date).format("YYYY-MM-DD HH:mm");
        if (grade === "1" || grade === "2") {
            result3[date] = true;
        }
        if (!result4[grade]) {
            result4[grade] = {};
        }
        result4[grade][date] = true;
    });


    const total_p1 = len(result2[1]) + len(result4[1])
    const total_p2 = len(result2[2]) + len(result4[2])
    const total_p3 = len(result2[3]) + len(result4[3])

    const total_p1p2 = total_p1 + total_p2
    var endTime = +new Date();
    time_consuming = Number(parseFloat(((endTime - beginTime) / 60000)).toFixed(3).slice(0, -1));
    logger.info("分析日志完毕，用时共计：" + time_consuming + "分钟");
    const log = `
  SLA定时任务已成功执行，执行时间为：${current_time}
  当前季度开始时间：${start_dt}
  截止此时总分钟数：${totalMinutes}分钟
  SLA【P1】级别日志汇总时间：${total_p1}分钟，其中业务：${len(result2[1])}分钟，算法：${len(result4[1])}分钟
  SLA【P2】级别日志汇总时间：${total_p2}分钟，其中业务：${len(result2[2])}分钟，算法：${len(result4[2])}分钟
  SLA【P3】级别日志汇总时间：${total_p3}分钟，其中业务：${len(result2[3])}分钟，算法：${len(result4[3])}分钟

  SLA【P1+P2】服务可用率为：${Number((100 - (total_p1p2 * 100) / totalMinutes).toString().match(/^\d+(?:\.\d{0,3})?/))}%
  SLA【P1】服务可用率为： ${Number((100 - (total_p1 * 100) / totalMinutes).toString().match(/^\d+(?:\.\d{0,3})?/))}%
  SLA【P2】服务可用率为： ${Number((100 - (total_p2 * 100) / totalMinutes).toString().match(/^\d+(?:\.\d{0,3})?/))}%
  SLA【P3】服务可用率为： ${Number((100 - (total_p3 * 100) / totalMinutes).toString().match(/^\d+(?:\.\d{0,3})?/))}%
  `;

    logger.info("开始钉钉消息推送：", log);
    message(log);
    logger.info("钉钉消息推送成功，程序结束！");
}

init();